package dessin;

import java.awt.*;
import java.util.Vector;

import javax.swing.*;

import patternobserver.Observateur;
import modele.*;
import modele.Point;
import modele.Rectangle;
/**
 * La classe VueDessin sert à afficher le dessin sur le Canevas. Pour cela elle se base sur le ModeleDessin qu'elle peut
 * atteindre par l'intermédiaire de ControleurDessin. La méthode paintComponent va d'abord dessiner la grille (en se basant sur le Pas dans le modele)
 * puis les axes X et Y sont dessinés, puis la forme tampon et enfin le Groupe.
 * @author Arnaud
 *
 */
public class VueDessin extends JPanel implements Observateur {


private ControleurDessin cDessin;
	
	public VueDessin(ControleurDessin cd) {
		super();
		this.cDessin=cd;
 		this.addMouseListener(cDessin);
 		this.addMouseMotionListener(cDessin);		
		this.setPreferredSize(cDessin.getmGeneral().getModDessin().getDimensionDessin());  
		this.setBackground(Color.white);
	}
	

	public void paintComponent(Graphics g) {
		super.paintComponent(g); //il vaut mieux d'apres la doc appeler d'abord le code du parent.
		
	    //Dessin de la grille et des axes
		dessinerGrille(g);
		dessinerAxes(g);
		
		// Dessin du groupe
		Groupe groupe = cDessin.getmGeneral().getModDessin().getGroupeDeFormes();
		dessinerGroupe(groupe,g);
		
		//Dessin de la formetampon		
		FormeGeometrique formetampon = cDessin.getmGeneral().getModDessin().getFormeTampon();
		Color c = cDessin.getmGeneral().getModPalette().getChoixColor();
		dessinerForme(formetampon,c, true, g);
	}

	
	private void dessinerForme(FormeGeometrique forme,Color c, Boolean fTampon, Graphics g) {
		
		if (forme instanceof Point)
		{
			Point p = (Point) forme;
			dessinerPoint(p,g);
		}
		
		if ( forme instanceof Polygone)
		{
			Polygone p = (Polygone) forme;
			dessinerPolygone(p,c,g,fTampon);	
		}
		
		if (forme instanceof Segment)
		{
		Segment s = (Segment) forme;
		dessinerSegment(s, c, g,fTampon);
		}
		
		if (forme instanceof Rectangle)
		{
			Rectangle rec = (Rectangle) forme;
			if (rec.getPremierPoint() != null) dessinerRectangle(rec, c, g);
		}
		
		if (forme instanceof Cercle)
		{
			Cercle cer = (Cercle) forme;
			if (cer.getOrigine() != null)	dessinerCercle(cer, c, g);
		}	
		
		if (forme instanceof Groupe)
		{	
			Groupe grp = (Groupe) forme;
			dessinerGroupe(grp, g);
		}
		
		
	}


	private void dessinerAxes(Graphics g) {
		
		//Dessin de l'axe des Y
			g.setColor(Color.red);
			g.drawLine((int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getWidth()/2,
				0,
				(int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getWidth()/2, 
				(int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getHeight());
		//Dessin de l'axe des X
		g.drawLine(0,
				(int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getHeight()/2,
				(int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getWidth(), 
				(int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getHeight()/2);
		g.setColor(Color.black);
		
	}


	private void dessinerGrille(Graphics g) {
		g.setColor(Color.lightGray);
		int hauteur = (int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getHeight();
		int largeur = (int) this.cDessin.getmGeneral().getModDessin().getDimensionDessin().getWidth();
		int abscisse0 = largeur/2;
		int ordonnee0 = hauteur/2;
		int pas = this.cDessin.getmGeneral().getModDessin().getPas();
		int nbPassageboucleTraitsVerticaux = abscisse0/pas+1;
		
		for(int i=1;i<nbPassageboucleTraitsVerticaux;i++)
		{
			g.drawLine(abscisse0+i*pas, 0,abscisse0+i*pas, hauteur);
			g.drawLine(abscisse0-i*pas, 0,abscisse0-i*pas, hauteur);
		}
		
		int nbPassageboucleTraitsHorizontaux = ordonnee0/pas+1;
		
		for(int i=1;i<nbPassageboucleTraitsHorizontaux;i++)
		{
			g.drawLine(0, ordonnee0+i*pas, largeur, ordonnee0+i*pas);
			g.drawLine(0, ordonnee0-i*pas, largeur, ordonnee0-i*pas);
		}
	}


	//methode qui permet de dessiner un Groupe
	private void dessinerGroupe(Groupe groupe, Graphics g){
		Vector<FormeGeometrique> vectorgroupe = groupe.getlesFormes();
		for (FormeGeometrique item : vectorgroupe) {
			Color c = item.getCouleur();
			dessinerForme(item, c, false, g);
		}
	}
	
	
	private void dessinerPolygone(Polygone p, Color c, Graphics g, boolean formeTampon){
		
		int nPoints = p.getListPoints().size();
		int[] xPoints = new int[nPoints];
		int[] yPoints = new int[nPoints];
		int i = 0;
		for (Point point : p.getListPoints()) {
			xPoints[i] = point.getX();
			yPoints[i] = point.getY();
			if (formeTampon) {g.fillOval(point.getX()-4,point.getY()-4,8,8);}
			i++;
		}
		
		if (p.isSelected()){
			Graphics2D g2D = (Graphics2D) g;     
		    g2D.setStroke(new BasicStroke(5F));
		    g2D.setColor(new Color((float)1,(float)0,(float) 0,(float) 0.5));
		    if (p.getClosed()) g2D.drawPolygon(xPoints, yPoints, nPoints);
			if (!p.getClosed()) g2D.drawPolyline(xPoints, yPoints, nPoints);
			g2D.setStroke(new BasicStroke(1F));
		}
		
		g.setColor(c);
		
		if (p.getClosed()) g.drawPolygon(xPoints, yPoints, nPoints);
		if (!p.getClosed()) g.drawPolyline(xPoints, yPoints, nPoints);
		
	}
	
	private void dessinerPoint(Point p, Graphics g){
		int taille = 10;
		if (p.isSelected()) 
			{
			g.setColor(new Color((float)1,(float)0,(float) 0,(float) 0.5));
			g.fillOval(p.getX()-(taille+10)/2, p.getY()-(taille+10)/2, taille+10, taille+10);
			}
		g.setColor(p.getCouleur());
		g.fillOval(p.getX()-taille/2, p.getY()-taille/2, taille, taille);
	}
	
	private void dessinerCercle(Cercle ce,Color c, Graphics g) {
		if (ce.isSelected()) {
			Graphics2D g2D = (Graphics2D) g;     
		    g2D.setStroke(new BasicStroke(5F));
		    g2D.setColor(new Color((float)1,(float)0,(float) 0,(float) 0.5));
			g.fillOval(ce.getOrigine().getX()-ce.getRayon()-5, ce.getOrigine().getY()-ce.getRayon()-5, ce.getRayon()*2+10, ce.getRayon()*2+10);
		    g2D.setStroke(new BasicStroke(1F));
		}
		g.setColor(ce.getCouleur());
		g.fillOval(ce.getOrigine().getX()-ce.getRayon(), ce.getOrigine().getY()-ce.getRayon(), ce.getRayon()*2, ce.getRayon()*2);
		
	}
	
	private void dessinerSegment(Segment s,Color c, Graphics g,boolean formeTampon){
		if (s.isSelected())
			{
			
			Graphics2D g2D = (Graphics2D) g;     
		    g2D.setStroke(new BasicStroke(5F));  
		    g2D.setColor(new Color((float)1,(float)0,(float) 0,(float) 0.5));
		    g2D.drawLine(s.getOrigine().getX(),s.getOrigine().getY(), s.getExtremite().getX(), s.getExtremite().getY());
		    
			g.setColor(s.getCouleur());
			g2D.setStroke(new BasicStroke(1F)); 
			g.drawLine(s.getOrigine().getX(),s.getOrigine().getY(), s.getExtremite().getX(), s.getExtremite().getY());	
			
			}
		else
			{
			
			g.setColor(c);
			if (s.getOrigine() != null && s.getExtremite() != null)
				{	
					g.drawLine(s.getOrigine().getX(),s.getOrigine().getY(), s.getExtremite().getX(), s.getExtremite().getY());	
						if (formeTampon) {
							g.drawLine(s.getOrigine().getX()-5, s.getOrigine().getY()-5, s.getOrigine().getX()+5, s.getOrigine().getY()+5);
							g.drawLine(s.getOrigine().getX()-5, s.getOrigine().getY()+5, s.getOrigine().getX()+5, s.getOrigine().getY()-5);
							g.drawLine(s.getExtremite().getX()-5, s.getExtremite().getY()-5, s.getExtremite().getX()+5, s.getExtremite().getY()+5);
							g.drawLine(s.getExtremite().getX()-5, s.getExtremite().getY()+5, s.getExtremite().getX()+5, s.getExtremite().getY()-5);
							}
		
				}	
		
			if (formeTampon && s.getOrigine() != null && s.getExtremite() == null)
			{		
				g.drawLine(s.getOrigine().getX()-5, s.getOrigine().getY()-5, s.getOrigine().getX()+5, s.getOrigine().getY()+5);
				g.drawLine(s.getOrigine().getX()-5, s.getOrigine().getY()+5, s.getOrigine().getX()+5, s.getOrigine().getY()-5);
			}	
			}
		}
	
	private void dessinerRectangle(Rectangle r,Color c, Graphics g){
		if (r.isSelected()) 
		{
			Graphics2D g2D = (Graphics2D) g;     
		    g2D.setStroke(new BasicStroke(5F));
		    g2D.setColor(new Color((float)1,(float)0,(float) 0,(float) 0.5));
		g2D.drawRect(r.getPremierPoint().getX(), r.getPremierPoint().getY(), r.getWidth(), r.getHeight());
		 g2D.setStroke(new BasicStroke(1F));
		}
		g.setColor(r.getCouleur());
		g.fillRect(r.getPremierPoint().getX(), r.getPremierPoint().getY(), r.getWidth(), r.getHeight());
	}


	@Override
	public void update() {
		this.repaint();
	}
}